// controllers/user.go
package controllers

import (
	"myapi/models"
	"myapi/repositories"
	"myapi/utils"
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
	"golang.org/x/crypto/bcrypt"
)

// UserController 处理用户相关请求
type UserController struct {
	repo repositories.UserRepository
}

// NewUserController 创建用户控制器实例
func NewUserController() *UserController {
	return &UserController{
		repo: repositories.UserRepository{},
	}
}

// Register 注册新用户
func (c *UserController) Register(ctx *gin.Context) {
	var user models.User
	if err := ctx.ShouldBindJSON(&user); err != nil {
		utils.ErrorResponse(ctx, http.StatusBadRequest, "请求数据错误")
		return
	}

	// 检查邮箱是否已存在
	existingUser, _ := c.repo.FindByEmail(user.Email)
	if existingUser != nil {
		utils.ErrorResponse(ctx, http.StatusConflict, "邮箱已存在,请重新注册")
		return
	}

	// 加密密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost)
	if err != nil {
		utils.ErrorResponse(ctx, http.StatusInternalServerError, "请求处理失败")
		return
	}
	user.Password = string(hashedPassword)

	// 创建用户
	if err := c.repo.Create(&user); err != nil {
		utils.ErrorResponse(ctx, http.StatusInternalServerError, "用户创建失败")
		return
	}

	utils.SuccessResponse(ctx, user.ToResponse(), "用户注册成功")
}

// GetUser 获取单个用户信息
func (c *UserController) GetUser(ctx *gin.Context) {
	idStr := ctx.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 64)
	if err != nil {
		utils.ErrorResponse(ctx, http.StatusBadRequest, "用户ID错误")
		return
	}

	user, err := c.repo.FindByID(uint(id))
	if err != nil {
		utils.ErrorResponse(ctx, http.StatusNotFound, "用户不存在")
		return
	}
	utils.SuccessResponse(ctx, user.ToResponse(), "用户获取成功")
}

// GetUsers 获取所有用户
func (c *UserController) GetUsers(ctx *gin.Context) {
	pageStr := ctx.DefaultQuery("page", "1")
	pageSizeStr := ctx.DefaultQuery("page_size", "10")

	page, _ := strconv.Atoi(pageStr)
	pageSize, _ := strconv.Atoi(pageSizeStr)

	if page < 1 {
		page = 1
	}
	if pageSize < 1 || pageSize > 100 {
		pageSize = 10
	}

	users, count, err := c.repo.FindAll(page, pageSize)
	if err != nil {
		utils.ErrorResponse(ctx, http.StatusInternalServerError, "用户获取失败")
		return
	}

	// 转换为响应格式
	var userResponses []models.UserResponse
	for _, user := range users {
		userResponses = append(userResponses, user.ToResponse())
	}

	data := gin.H{
		"users":      userResponses,
		"total":      count,
		"page":       page,
		"page_size":  pageSize,
		"total_page": (count + int64(pageSize) - 1) / int64(pageSize),
	}

	utils.SuccessResponse(ctx, data, "用户获取成功")
}

// UpdateUser 更新用户信息
func (c *UserController) UpdateUser(ctx *gin.Context) {
	idStr := ctx.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 64)
	if err != nil {
		utils.ErrorResponse(ctx, http.StatusBadRequest, "用户ID错误")
		return
	}

	user, err := c.repo.FindByID(uint(id))
	if err != nil {
		utils.ErrorResponse(ctx, http.StatusNotFound, "用户不存在")
		return
	}

	var updateData struct {
		Name     string `json:"name"`
		Email    string `json:"email"`
		Password string `json:"password"`
	}

	if err := ctx.ShouldBindJSON(&updateData); err != nil {
		utils.ErrorResponse(ctx, http.StatusBadRequest, "请求数据错误")
		return
	}

	// 更新字段
	if updateData.Name != "" {
		user.Name = updateData.Name
	}
	if updateData.Email != "" && updateData.Email != user.Email {
		// 检查新邮箱是否已存在
		existingUser, _ := c.repo.FindByEmail(updateData.Email)
		if existingUser != nil {
			utils.ErrorResponse(ctx, http.StatusConflict, "邮箱已存在,请重新注册")
			return
		}
		user.Email = updateData.Email
	}
	if updateData.Password != "" {
		hashedPassword, err := bcrypt.GenerateFromPassword([]byte(updateData.Password), bcrypt.DefaultCost)
		if err != nil {
			utils.ErrorResponse(ctx, http.StatusInternalServerError, "请求处理失败")
			return
		}
		user.Password = string(hashedPassword)
	}

	if err := c.repo.Update(user); err != nil {
		utils.ErrorResponse(ctx, http.StatusInternalServerError, "用户更新失败")
		return
	}

	utils.SuccessResponse(ctx, user.ToResponse(), "用户更新成功")
}

// DeleteUser 删除用户
func (c *UserController) DeleteUser(ctx *gin.Context) {
	idStr := ctx.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 64)
	if err != nil {
		utils.ErrorResponse(ctx, http.StatusBadRequest, "用户ID错误")
		return
	}

	if err := c.repo.Delete(uint(id)); err != nil {
		utils.ErrorResponse(ctx, http.StatusInternalServerError, "用户删除失败")
		return
	}

	utils.SuccessResponse(ctx, nil, "用户删除成功")
}
